package com.bdv.md.service.impl;

import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.bdv.md.dao.DmTblDao;
import com.bdv.md.dao.MapTblDao;
import com.bdv.md.job.MeterReadingJob;
import com.bdv.md.model.DmTbl;
import com.bdv.md.model.MapTbl;
import com.bdv.md.service.JobService;
import com.bdv.md.service.impl.TransactionServiceImpl;

@Service("jobService")
@Transactional(readOnly = true)
public class JobServiceImpl implements JobService {

	Logger logger = Logger.getLogger(this.getClass());
	
	@Autowired
	private MapTblDao mapTblDao;
	@Autowired
	private DmTblDao dmTblDao;
	private Scheduler scheduler;
	
	public JobServiceImpl(){
		if(scheduler==null){
			try {
				scheduler = StdSchedulerFactory.getDefaultScheduler();
			} catch (SchedulerException e) {
				e.printStackTrace();
			}
		}
	}
	/*
	 * Meter reading schedule for all mapped meter
	 */
	public void meterReadingJob() {
		List<MapTbl> mapTbls = mapTblDao.findAll();
		try {
			if(scheduler.isShutdown()){
				scheduler = StdSchedulerFactory.getDefaultScheduler();
			}
			for(MapTbl mapTbl : mapTbls){		
				if(mapTbl.getInterval()!=0){
					JobDetail job = JobBuilder.newJob(MeterReadingJob.class)
							.withIdentity( mapTbl.getMapId().toString(), "MeterReading").build();
					
					job.getJobDataMap().put("mapTbl", mapTbl);
					
					Trigger trigger = TriggerBuilder.newTrigger()
							.withIdentity( mapTbl.getMapId().toString(), "MeterReading")
							.withSchedule(
								SimpleScheduleBuilder.simpleSchedule()
									.withIntervalInMilliseconds(mapTbl.getInterval())
									.repeatForever())
							.startNow()
							.build();
						scheduler.scheduleJob(job, trigger);
				}
			}
			if(mapTbls !=null && mapTbls.size()>0 && !scheduler.isStarted()){
				scheduler.start();
			}
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
		
		
		
	}

	public void meterReadingJob(MapTbl mapTbl) {
		System.out.println("Create Job : "+mapTbl);
		try {	
			if(mapTbl.getInterval()!=0){
				
				JobDetail job = JobBuilder.newJob(MeterReadingJob.class)
						.withIdentity( mapTbl.getMapId().toString(), "MeterReading").build();
				
				job.getJobDataMap().put("mapTbl", mapTbl);
				
				Trigger trigger = TriggerBuilder.newTrigger()
						.withIdentity( mapTbl.getMapId().toString(), "MeterReading")
						.withSchedule(
							SimpleScheduleBuilder.simpleSchedule()
								.withIntervalInMilliseconds(mapTbl.getInterval())
								.repeatForever())
						.startNow()
						.build();
					scheduler.scheduleJob(job, trigger);
					if(!scheduler.isStarted()){
						scheduler.start();
					}
				System.out.println("Job Completed.. "+mapTbl);
			}else{
				System.out.println("Job Interval cannot be zero");
			}
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
		
		
	}
	
	
	public String updateMeterReadingSchedule(MapTbl mapTbl){
		try {	

			TriggerKey oldTriggerKey = new TriggerKey(mapTbl.getMapId().toString(), "MeterReading");
			
			Trigger newTrigger = TriggerBuilder.newTrigger()
					.withIdentity( mapTbl.getMapId().toString(), "MeterReading")
					.withSchedule(
						SimpleScheduleBuilder.simpleSchedule()
							.withIntervalInMilliseconds(mapTbl.getInterval())
							.repeatForever())
					.startNow()
					.build();
			
			scheduler.rescheduleJob(oldTriggerKey, newTrigger);
			return "1";
		} catch (SchedulerException e) {
			e.printStackTrace();
			return "0";
		}
	}
	
	public String stopJob(String key){
		try {
			scheduler.deleteJob(new JobKey(key, "MeterReading"));
			System.out.println("Stopping Job: "+key);
			return "1";
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "0";
		}
	}
	
	public void stopSchedule(){
		System.out.println("Stopping Schedule..");
		try {
			scheduler.clear();
			scheduler.shutdown(true);
			scheduler=null;
			Thread.sleep(1000);
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException ie){
			ie.printStackTrace();
		}
		
	}
	
	public void saveNewMeterReading(DmTbl dmTbl){
		dmTblDao.saveOrUpdate(dmTbl);
	}
	public String openKeran(MapTbl mapTbl, Integer interval, String jobId) {

		try {	
			JobDetail job = JobBuilder.newJob(MeterReadingJob.class)
					.withIdentity( jobId, "MeterReadingKeran").build();
			
			job.getJobDataMap().put("mapTbl", mapTbl);
			job.getJobDataMap().put("trxId", jobId);
			
			Trigger trigger = TriggerBuilder.newTrigger()
					.withIdentity( jobId, "MeterReadingKeran")
					.withSchedule(
						SimpleScheduleBuilder.simpleSchedule()
							.withIntervalInMilliseconds(interval)
							.repeatForever())
					.startNow()
					.build();
				scheduler.scheduleJob(job, trigger);
				if(!scheduler.isStarted()){
					scheduler.start();
				}
				return "1";
		} catch (SchedulerException e) {
			e.printStackTrace();
			return "0";
		}
		
	}
	public String closeKeran(String jobId) {
		try {
			scheduler.deleteJob(new JobKey(jobId, "MeterReadingKeran"));
			
			logger.debug("Delete Job, ID: "+jobId);
			System.out.println("Delete Job, ID: "+jobId);
			return "1";
		} catch (SchedulerException e) {
			e.printStackTrace();
			return "0";
		}
	}
	
	
}
